<?php if ( ! defined('BASEPATH')) exit('This file does not run directly. Sorry.'); ?>
<?php
/**
 * Kalaisoo.
 *
 * A lightweight no-framework framework written in PHP.
 *
 * @package Kalaisoo
 * @author $Author: info@sah-company.com $
 * @version $Id: permission.php 126 2012-01-11 20:59:15Z info@sah-company.com $
 */

/**
 * Kalaisoo Permission Class.
 *
 * @package Kalaisoo
 * @subpackage System
 * @author $Author: info@sah-company.com $
 */
class Permission
{

	/**
	 * constructs a new Permission object.
	 *
	 * @return void
	 */
	public function __construct()
	{
	}

	/**
	 * returns wether the user has permission to do action on domain of id.
	 *
	 * When called this will check for a valid user. If there is one it will firstly check
	 * if the user is admin. If so it will return true.
	 * Otherwise it will check the role based permission system to see if user has access
	 * to the domain and the concreate record of the domain if parameter $id is given.
	 *
	 * @param mixed $user
	 * @param string $action
	 * @param string $domain
	 * @param mixed $id
	 * @return bool
	 */
	public function granted($user, $action, $domain, $id = null)
	{
		if ( ! $user || ! $user->getId()) {
			return false;
		}
		$this->loadPermissions($user);
		if ($user->admin) return true;
		return $this->checkPermissions(strtolower($action), strtolower($domain), $id);
	}
	
	/**
	 * returns an key/value array of all domains where user can do action.
	 *
	 * @param mixed $user
	 * @param string $action
	 * @return array
	 */
	public function domains($user, $action)
	{
		if ( ! $user || ! $user->getId()) {
			return array();
		}
		$this->loadPermissions($user);
		$ret = array();
		foreach ($_SESSION['permissions'] as $domain=>$actions) {
			if (isset($actions[$action]) && $actions[$action]) {
				$ret[$domain] = __($domain); // localized name
			}
		}
		asort($ret);
		return $ret;
	}
	
	/**
	 * returns an array of all actions of a domain user may access.
	 *
	 * @param mixed $user
	 * @param string $domain
	 * @return array
	 */
	public function actions($user, $domain)
	{
		if ( ! $user || ! $user->getId()) {
			return array();
		}
		$this->loadPermissions($user);
		if ( ! isset($_SESSION['permissions'][$domain])) return array();
		return $_SESSION['permissions'][$domain];
	}
	
	/**
	 * returns wether an action can be performed on a certain domain record.
	 *
	 * @param string $action
	 * @param string $domain
	 * @param mixed $id
	 * @return bool
	 */
	protected function checkPermissions($action, $domain, $id = null)
	{
		if (isset($_SESSION['permissions'][$domain][$action]) && $_SESSION['permissions'][$domain][$action]) {
			// yeah, you can do that
			return true;
		}
		// whoops, you can not do that
		return false;
	}
	
	/**
	 * loads the permission into the users session variables.
	 *
	 * This will load and cache the permissions in $_SESSION['permissions'] from
	 * the database.
	 *
	 * @param mixed $user The user bean
	 * @return void
	 */
	protected function loadPermissions($user)
	{
		if (isset($_SESSION['permissions']) && is_array($_SESSION['permissions'])) {
			return;
		}
		$roles = R::related($user, 'rbac_role');
		if ( ! $roles) return;
		$rbacs = R::find('rbac', ' rbac_role_id IN ('.R::genSlots(array_keys($roles)).')', array_keys($roles));
		foreach ($rbacs as $n=>$rbac) {
			foreach ($rbac->ownRbac_permission as $m=>$permission) {
				$_SESSION['permissions'][strtolower($rbac->rbac_domain->name)][strtolower($permission->rbac_action->name)] = $permission->is_allowed;
			}
		}
		return;
	}
}
?>